package com.god.liu.gateway.filters.authfilter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import java.util.Arrays;
import java.util.List;

/**
 * 默认是name+GatewayFilterFactory作为自定义局部过滤器的类名，一定要注意，这样才能和yml里配置一致
 */
@Component
public class TimeGatewayFilterFactory extends AbstractGatewayFilterFactory<TimeGatewayFilterFactory.Config> {

    private Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * 定义可以再yaml中声明的属性变量
     */
    private static final String TYPE = "type";
    private static final String OP = "action";

    public TimeGatewayFilterFactory(){
        // 这里需要将自定义的config传过去，否则会报告ClassCastException
        super(Config.class);
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList(TYPE, OP);
    }

    @Override
    public GatewayFilter apply(Config config) {
        return ((exchange, chain) -> {
            boolean root = "root".equals(config.getAction());
            if (root){
                logger.info("GatewayFilter root");
            }
            else {
                logger.info("GatewayFilter customer");
            }
            // 在then方法里的，相当于aop中的后置通知
            Long startTime = System.currentTimeMillis();
            return chain.filter(exchange).then(Mono.fromRunnable(()->{
                // do something
                logger.info(System.currentTimeMillis()+"");

                //调用请求之后统计时间
                Long endTime = System.currentTimeMillis();
                System.out.println(exchange.getRequest().getURI().getRawPath() + ", cost time : " + (endTime - startTime) + "ms");
            }));
        });
    }

    public static class Config{
        /**
         * 从yml文件里读取属性
         */
        String type;
        /**
         * 从yml文件里读取属性
         */
        String action;

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }

        public String getAction() {
            return action;
        }

        public void setAction(String action) {
            this.action = action;
        }
    }

}
